﻿/********
* 
* 
*  Description:
*  Create By kain.hong at 7/20/2010 11:21:34 AM
*  
*
*  Revision History:
*  Date                  Who                 What
*  
* 
*/
#region namespace

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Threading;
using Microsoft.Practices.Unity;
using Cherry.Agile.Core;
using System.Diagnostics;

#endregion


namespace Cherry.Agile.Data.DataAccess
{
    /// <summary>
    /// 定义Connection的包装器
    /// </summary>
    internal class DbConnectionWrapper : IDisposable
    {
        private int refCount;

        public event EventHandler Disposed;
       
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connection">DbConnection 实例</param>
        public DbConnectionWrapper(DbConnection connection)
        {
            Connection = connection;
            Debug.Assert(connection != null);
            connection.Disposed += new EventHandler(connection_Disposed);
            refCount = 1;
            
        }

        void connection_Disposed(object sender, EventArgs e)
        {
            refCount = 0;
            this.Dispose();
        }

        /// <summary>
        /// 当前的Connection <see cref="DbConnection"/> 
        /// </summary>
        public DbConnection Connection { get; private set; }

        /// <summary>
        /// 判断当前实例是否已经Disposed
        /// </summary>
        public bool IsDisposed
        {
            get { return Connection == null || refCount == 0; }
        }

        #region IDisposable Members

        /// <summary>
        /// Decrement the reference count and, if refcount is 0, close the underlying connection.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Interlocked.Decrement(ref refCount);

            Dispose(refCount == 0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                Connection.Disposed -= new EventHandler(connection_Disposed);

                System.Diagnostics.Trace.TraceInformation("DbConnectionWrapper\t{0:G} {1}:Connection disposed", DateTime.Now, Connection.GetHashCode());
                if (Disposed != null)
                    Disposed(this, EventArgs.Empty);
                Connection.Dispose();

                Connection = null;
                
                GC.SuppressFinalize(this);
               
            }
        }

        #endregion

        /// <summary>
        /// 被使用次数，引用一次计数器加1
        /// </summary>
        public DbConnectionWrapper AddRef()
        {
            Interlocked.Increment(ref refCount);
            return this;
        }
    }
}
